home *** CD-ROM | disk | FTP | other *** search
/ Internet Info 1994 March / Internet Info CD-ROM (Walnut Creek) (March 1994).iso / networking / ip / ka9q / osrc.arc / ICMP.C < prev    next >
Encoding:
C/C++ Source or Header  |  1989-01-11  |  5.2 KB  |  207 lines

  1. /* Internet Control Message Protocol */
  2. #include "global.h"
  3. #include "mbuf.h"
  4. #include "internet.h"
  5. #include "timer.h"
  6. #include "iface.h"
  7. #include "ip.h"
  8. #include "icmp.h"
  9.  
  10. extern int32 Ip_addr;    /* Our IP address */
  11. struct mbuf *htonicmp();
  12. struct mbuf *htonip();
  13.  
  14. struct icmp_errors Icmp_errors;
  15. struct icmp_stats Icmp_stats;
  16.  
  17. /* Process an incoming ICMP packet */
  18. void
  19. icmp_input(bp,protocol,source,dest,tos,length,rxbroadcast)
  20. struct mbuf *bp;    /* Pointer to ICMP message */
  21. char protocol;        /* Should always be ICMP_PTCL */
  22. int32 source;        /* Sender of ICMP message */
  23. int32 dest;        /* Us */
  24. char tos;        /* Type of Service */
  25. int16 length;        /* Length of ICMP message */
  26. char rxbroadcast;
  27. {
  28.     struct mbuf *tbp;
  29.     struct icmp icmp;    /* ICMP header */
  30.     struct ip ip;        /* Offending datagram header */
  31.     int16 type;        /* Type of ICMP message */
  32.  
  33.     if(rxbroadcast){
  34.         /* Broadcast ICMP packets are to be IGNORED !! */
  35.         Icmp_errors.bdcsts++;
  36.         free_p(bp);
  37.         return;
  38.     }
  39.     if(cksum(NULLHEADER,bp,length) != 0){
  40.         /* Bad ICMP checksum; discard */
  41.         Icmp_errors.checksum++;
  42.         free_p(bp);
  43.         return;
  44.     }
  45.     ntohicmp(&icmp,&bp);
  46.  
  47.     /* Process the message. Some messages are passed up to the protocol
  48.      * module for handling, others are handled here.
  49.      */
  50.     type = icmp.type;
  51.     if(type < ICMP_TYPES)
  52.         Icmp_stats.input[type]++;
  53.  
  54.     switch(uchar(type)){
  55.     case TIME_EXCEED:    /* Time-to-live Exceeded */
  56.     case DEST_UNREACH:    /* Destination Unreachable */
  57.     case QUENCH:        /* Source Quench */
  58.         ntohip(&ip,&bp);    /* Extract offending IP header */
  59.         switch(uchar(ip.protocol)){
  60.         case TCP_PTCL:
  61.             tcp_icmp(ip.source,ip.dest,icmp.type,icmp.code,&bp);
  62.             break;
  63.         }
  64.         break;
  65.     case ECHO:        /* Echo Request */
  66.         /* Change type to ECHO_REPLY, recompute checksum,
  67.          * and return datagram.
  68.          */
  69.         icmp.type = ECHO_REPLY;
  70.         if((tbp = htonicmp(&icmp,bp)) == NULLBUF){
  71.             free_p(bp);
  72.             return;
  73.         }
  74.         Icmp_stats.output[ECHO_REPLY]++;
  75.         ip_send(dest,source,ICMP_PTCL,tos,0,tbp,length,0,0);
  76.         return;
  77.     case REDIRECT:        /* Redirect */
  78.     case PARAM_PROB:    /* Parameter Problem */
  79.         break;
  80.        case ECHO_REPLY:        /* Echo Reply */
  81. #ifdef    notdef
  82.         echo_proc(source,dest,&icmp,bp);
  83.         bp = NULLBUF;    /* so it won't get freed */
  84. #endif
  85.         break;
  86.     case TIMESTAMP:        /* Timestamp */
  87.     case TIME_REPLY:    /* Timestamp Reply */
  88.     case INFO_RQST:        /* Information Request */
  89.     case INFO_REPLY:    /* Information Reply */
  90.         break;
  91.     }
  92.     free_p(bp);
  93. }
  94. /* Return an ICMP response to the sender of a datagram.
  95.  * Unlike most routines, the callER frees the mbuf.
  96.  */
  97. int
  98. icmp_output(ip,data,type,code,args)
  99. struct ip *ip;        /* Header of offending datagram */
  100. struct mbuf *data;    /* Data portion of datagram */
  101. char type,code;        /* Codes to send */
  102. union icmp_args *args;
  103. {
  104.     struct mbuf *bp;
  105.     struct icmp icmp;    /* ICMP protocol header */
  106.     int16 dlen;        /* Length of data portion of offending pkt */
  107.     int16 length;        /* Total length of reply */
  108.  
  109.     if(ip == NULLIP)
  110.         return -1;
  111.     if(uchar(ip->protocol) == ICMP_PTCL){
  112.         /* Never send an ICMP message about another ICMP message */
  113.         Icmp_errors.noloop++;
  114.         return -1;
  115.     }
  116.     if(type < ICMP_TYPES)
  117.         Icmp_stats.output[type]++;
  118.  
  119.     /* Compute amount of original datagram to return.
  120.      * We return the original IP header, and up to 8 bytes past that.
  121.      */
  122.     dlen = min(8,len_mbuf(data));
  123.     length = dlen + ICMPLEN + IPLEN + ip->optlen;
  124.     /* Take excerpt from data portion */
  125.     if(data != NULLBUF && dup_p(&bp,data,0,dlen) == 0)
  126.         return -1;    /* The caller will free data */
  127.  
  128.     /* Recreate and tack on offending IP header */
  129.     if((data = htonip(ip,bp)) == NULLBUF){
  130.         free_p(bp);
  131.         return -1;
  132.     }
  133.     icmp.type = type;
  134.     icmp.code = code;
  135.     switch(uchar(icmp.type)){
  136.     case PARAM_PROB:
  137.         icmp.args.pointer = args->pointer;
  138.         break;
  139.     case REDIRECT:
  140.         icmp.args.address = args->address;
  141.         break;
  142.     case ECHO:
  143.     case ECHO_REPLY:
  144.     case INFO_RQST:
  145.     case INFO_REPLY:
  146.     case TIMESTAMP:
  147.     case TIME_REPLY:
  148.         icmp.args.echo.id = args->echo.id;
  149.         icmp.args.echo.seq = args->echo.seq;
  150.         break;
  151.     default:
  152.         icmp.args.unused = 0;
  153.         break;
  154.     }
  155.     /* Now stick on the ICMP header */
  156.     if((bp = htonicmp(&icmp,data)) == NULLBUF){
  157.         free_p(data);
  158.         return -1;
  159.     }
  160.     return ip_send(Ip_addr,ip->source,ICMP_PTCL,ip->tos,0,bp,length,0,0);
  161. }
  162. /* Generate ICMP header in network byte order, link data, compute checksum */
  163. struct mbuf *
  164. htonicmp(icmp,data)
  165. struct icmp *icmp;
  166. struct mbuf *data;
  167. {
  168.     struct mbuf *bp;
  169.     register char *cp;
  170.     int16 checksum;
  171.  
  172.     if((bp = pushdown(data,ICMPLEN)) == NULLBUF)
  173.         return NULLBUF;
  174.     cp = bp->data;
  175.  
  176.     *cp++ = icmp->type;
  177.     *cp++ = icmp->code;
  178.     cp = put16(cp,0);        /* Clear checksum */
  179.     cp = put16(cp,icmp->args.echo.id);
  180.     cp = put16(cp,icmp->args.echo.seq);
  181.  
  182.     /* Compute checksum, and stash result */
  183.     checksum = cksum(NULLHEADER,bp,len_mbuf(bp));
  184.     cp = &bp->data[2];
  185.     cp = put16(cp,checksum);
  186.  
  187.     return bp;
  188. }
  189. /* Pull off ICMP header */
  190. int
  191. ntohicmp(icmp,bpp)
  192. struct icmp *icmp;
  193. struct mbuf **bpp;
  194. {
  195.     char icmpbuf[8];
  196.  
  197.     if(icmp == (struct icmp *)NULL)
  198.         return -1;
  199.     if(pullup(bpp,icmpbuf,8) != 8)
  200.         return -1;
  201.     icmp->type = icmpbuf[0];
  202.     icmp->code = icmpbuf[1];
  203.     icmp->args.echo.id = get16(&icmpbuf[4]);
  204.     icmp->args.echo.seq = get16(&icmpbuf[6]);
  205.     return 0;
  206. }
  207.